// (c) Copyright 2013-2014 Stephen Gold <sgold@sonic.net>
// Distributed under the terms of the GNU General Public License

/*
 This file is part of the Bats Game.

 The Bats Game is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by the
 Free Software Foundation, either version 3 of the License, or (at your
 option) any later version.

 The Bats Game is distributed in the hope that it will be useful, but
 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 for more details.

 You should have received a copy of the GNU General Public License
 along with the Bats Game.  If not, see <http://www.gnu.org/licenses/>.
 */
package bats.unit;

import bats.Assets;
import bats.indicator.TargetIndicator;
import bats.scene.IndicatorsNode;
import bats.scene.SceneNode;
import bats.scene.WorldNode;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.Bucket;
import com.jme3.scene.Geometry;
import java.util.Collection;
import java.util.Iterator;
import java.util.logging.Logger;
import jme3utilities.SimpleControl;

/**
 * A simple control for a target indicator. When this control is enabled, its
 * target indicator becomes visible.
 * <p>
 * Each instance is disabled at creation.
 *
 * @author Stephen Gold <sgold@sonic.net>
 */
public class TargetControl
        extends SimpleControl {
    // *************************************************************************
    // constants

    /**
     * color of the target indicator
     */
    final private static ColorRGBA color = ColorRGBA.White;
    /**
     * message logger for this class
     */
    final private static Logger logger =
            Logger.getLogger(TargetControl.class.getName());
    /**
     * type of indicator
     */
    final private static String indicatorType = "target";
    // *************************************************************************
    // fields
    /**
     * the indicator geometry
     */
    private Geometry indicator = null;
    // *************************************************************************
    // constructors

    /**
     * Instantiate a disabled control.
     */
    public TargetControl() {
        super.setEnabled(false);
    }
    // *************************************************************************
    // new methods exposed

    /**
     * Get the world location of the target indicator.
     *
     * @return a new vector
     */
    public Vector3f getIndicatorLocation() {
        assert spatial != null;

        UnitClass units = WorldNode.find(spatial).getUnitClass(spatial);
        Collection<Vector3f> locations = units.getTargets(spatial);
        Iterator<Vector3f> it = locations.iterator();

        Vector3f location = it.next().clone();
        return location;
    }
    // *************************************************************************
    // AbstractControl methods

    /**
     * Alter this control's enabled status.
     *
     * @param newState true to enable (reveal indicator), false to disable (hide
     * indicator)
     */
    @Override
    public void setEnabled(boolean newState) {
        assert spatial != null;
        createIndicator();
        assert indicator != null;
        IndicatorsNode indicators = SceneNode.find(spatial).getIndicators();
        if (isEnabled() && !newState) {
            indicators.detach(indicator);
        } else if (!isEnabled() && newState) {
            indicators.reveal(indicator);
        }
        super.setEnabled(newState);
    }
    // *************************************************************************
    // private methods

    /**
     * Create the indicator for the unit.
     */
    private void createIndicator() {
        if (indicator != null) {
            /*
             * The indicator has already been created.
             */
            return;
        }
        assert spatial != null;

        indicator = Assets.loadIndicatorModel(indicatorType);
        String name = String.format("%s %s indicator",
                spatial.getName(), indicatorType);
        indicator.setName(name);

        Material material = Assets.createUnshadedMaterial(color);
        material.getAdditionalRenderState().setDepthTest(false);
        indicator.setMaterial(material);
        indicator.setQueueBucket(Bucket.Translucent);

        TargetIndicator indicatorControl =
                new TargetIndicator(this);
        indicator.addControl(indicatorControl);

        UnitClass units = WorldNode.find(spatial).getUnitClass(spatial);
        float scale = units.getRelativeSize(spatial);
        scale /= SceneNode.find(spatial).getScaleFactor();
        indicator.setLocalScale(scale);

        if (isEnabled()) {
            SceneNode.find(spatial).getIndicators().reveal(indicator);
        }
    }
}